Results
This section shows preliminary results for Black sea bass (Centropristis striata).
# Load interpolated data
# "Centropristis striata"
#
historic_tif <- my_path("R","Partial/Interpolation","tif_Centropristis_striata.csv", read = T)
# Spatial data
States <- c("maine", "new hampshire", "massachusetts", "connecticut", "rhode island", "new york", "new jersey", "delaware", "maryland", "virginia", "north carolina","pennsylvania")
# US State Map (land)
land_sf <- st_as_sf(map("state", plot = FALSE, fill = TRUE)) %>%
filter(ID %in% States)
# Periods
periods <-tibble(
period = c(rep("a early",12),
rep("b mid",12),
rep("c late",12),
rep("d now",12)
),
year = c(seq(1972,1984,1),
seq(1985,1997,1),
seq(1998,2011,1),
seq(2012,2019,1)
)
)
# State pallet
state_pallet <- c(wes_palette(n = 5, name = "Darjeeling1"),
wes_palette(n = 5, name = "Darjeeling2"),
wes_palette(n = 3, name = "Royal1")
)
# print for notebook
head(historic_tif)
Average proportion
This map shows the average proportion of the extrapolated value from the whole study period within each State’s water.
Note: Grey tiles represent NAs

Proportion Change
Here we show the average proportion of the interpolation by State and time period. Time periods were arbitrary defined as;
- Early; 1972 to 1984
- Mid; 1985 to 1997
- Late; 1998 to 2011
- Now; 2012 to 2019
Notes: To panel represents Fall survey and bottom panel Spring. This computation considers the Overlapping of state waters.
total_fited <- historic_tif %>%
group_by(year,region) %>%
summarise(total_value = sum(value,na.rm=T),.groups = "drop")
state_fit <- historic_tif %>%
group_by(state,year,region) %>%
summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>%
left_join(total_fited,
by = c("year","region")) %>%
mutate(percentage = state_value/total_value*100) %>%
left_join(periods) %>%
group_by(ID = state,period,region) %>%
summarise(mean_per = round(mean(percentage)),.groups = "drop")
Joining, by = "year"
# check percentages
# state_fit %>%
# group_by(period) %>%
# summarise(sum(mean_per))
land_sf %>%
left_join(state_fit,
by = "ID") %>%
ggplot() +
geom_sf(aes(fill = mean_per)) +
viridis::scale_fill_viridis("Mean Proportion", alpha = 0.8) +
facet_wrap(~region + period, nrow = 2) +
my_ggtheme_m()

Area plot
This graph shows the proportion of the interpolation value each State has over time.
Note: This plot is interactive. For ease comparison between States you can;
- One click on any State to remove it from the plot
- Two clicks on any State to isolate it from the plot (other states can then be added by just clicking on them).
- The bottom panel allows you to reduce the time frame
total_fited <- historic_tif %>%
group_by(year,region) %>%
summarise(total_value = sum(value,na.rm=T),.groups = "drop")
# group by state
state_fit <- historic_tif %>%
group_by(state,year,region) %>%
summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>%
left_join(total_fited,
by = c("year","region")) %>%
mutate(percentage = state_value/total_value*100)
p <- ggplot(state_fit) +
geom_area(
aes(
x = year,
y = round(percentage),
fill = state
)
) +
ylab("Percentage (%)") +
# viridis::scale_fill_viridis(discrete = T, alpha = 0.8) +
scale_fill_manual(values = state_pallet) +
MyFunctions::my_ggtheme_p() +
facet_wrap(~region, ncol = 1)
ggplotly(p,
dynamicTicks = TRUE) %>%
layout(hovermode = "x") %>%
rangeslider()
NA
Area plot (running mean)
This graph shows the proportion of each State smoothed over a *10 years running mean**. It allows to better see increasing and decreasing trends.
Note: This plot is also interactive and thus, follows the same options of the previous one.
# group by state
state_fit <- historic_tif %>%
group_by(state,year,region,.groups = "drop") %>%
summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>%
left_join(total_fited,
by = c("year","region")) %>%
mutate(percentage = state_value/total_value*100) %>%
group_by(state,region) %>%
mutate(RMean = zoo::rollmean(x = percentage,
10,
fill = NA,
na.rm=T)
)
# Plot me
p <- ggplot(state_fit) +
geom_area(
aes(
x = year,
y = round(RMean),
fill = state
)
) +
ylab("10 yrs running average (%)") +
# viridis::scale_fill_viridis(discrete = T, alpha = 0.8) +
scale_fill_manual(values = state_pallet) +
MyFunctions::my_ggtheme_p() +
facet_wrap(~region, ncol = 1)
suppressWarnings(
ggplotly(p,
dynamicTicks = TRUE) %>%
layout(hovermode = "x") %>%
# add_trace() %>%
rangeslider()
)
NA
LS0tCnRpdGxlOiAiU3BhdGlhbCBBbmFseXNpcyIKYXV0aG9yOiAiSnVsaWFubyBQYWxhY2lvcyBBYnJhbnRlcyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICB0aGVtZTogZGFya2x5Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoTXlGdW5jdGlvbnMpCk15RnVuY3Rpb25zOjpteV9saWIoYygiZ2dtYXAiLCJzZiIsInRpZHl2ZXJzZSIsInRvb2xzIiwicmVhZHIiLCJkYXRhLnRhYmxlIiwibWFwcyIsInZpcmlkaXMiLCJ3ZXNhbmRlcnNvbiIsImtuaXRyIiwia2FibGVFeHRyYSIsInBsb3RseSIpKQpgYGAKCiMgTWV0aG9kcwoKIyMgU3BhdGlhbCBkYXRhIHByZXBhcmF0aW9uCgojIyMgTG9hZCBkYXRhCgojIyMjIE1hcHMgZGF0YQoKV2UgdXNlIHRocmVlIGRpZmZlcmVudCBzaGFwZWZpbGVzIGZvciB0aGUgY29udGluZW50YWwgVS5TLiBsYW5kIG1hc3MsIHRoZSBTdGF0ZSB3YXRlcnMgb2YgbWFpbmUsIG5ldyBoYW1wc2hpcmUsIG1hc3NhY2h1c2V0cywgY29ubmVjdGljdXQsIHJob2RlIGlzbGFuZCwgbmV3IHlvcmssIG5ldyBqZXJzZXksIGRlbGF3YXJlLCBtYXJ5bGFuZCwgdmlyZ2luaWEsIG5vcnRoIGNhcm9saW5hIGFuZCB0aGUgTm9ydGggRWFzdCBFRVouCgoxLi0gKipMYW5kIHNoYXBlZmlsZTsqKiBjb3ZlcnMgdGhlIFVTIGxhbmQgdGVycml0b3J5IGZvciB2aXN1YWxpemF0aW9uLiBEYXRhIHByb3ZpZGVkIGZyb20gdGhlIGBtYXBgIHBhY2thZ2UuCgoyLi0gKipTdGF0ZSB3YXRlcnM7KiogY292ZXJzIHRoZSBzdGF0ZSB3YXRlcnMgb2YgdGhlIE5FIFVTIHN0YXRlcy4gRGF0YSBmcm9tIFtkYXRhLmdvdl0oaHR0cHM6Ly9jYXRhbG9nLmRhdGEuZ292L2RhdGFzZXQvZmVkZXJhbC1hbmQtc3RhdGUtd2F0ZXJzKS4gIAoKKkxpY2Vuc2U6IE5vIGxpY2Vuc2UgaW5mb3JtYXRpb24gd2FzIHByb3ZpZGVkLiBJZiB0aGlzIHdvcmsgd2FzIHByZXBhcmVkIGJ5IGFuIG9mZmljZXIgb3IgZW1wbG95ZWUgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgZ292ZXJubWVudCBhcyBwYXJ0IG9mIHRoYXQgcGVyc29uJ3Mgb2ZmaWNpYWwgZHV0aWVzIGl0IGlzIGNvbnNpZGVyZWQgYSBVLlMuIEdvdmVybm1lbnQgV29yay4qCgozLi0gKipFRVogc2hhcGVmaWxlOyoqIFVzZWQgdGhlICpTZWEgQXJvdW5kIFVzKiBzaGFwZWZsZSB1cGRhdGVkIHRvIEp1bmUgMjAxNi4KCmBgYHtyIG1hcHNfc2YsIGV2YWwgPSBULCBlY2hvID0gVCwgcmVzdWx0cyA9ICdoaWRlJ30KClN0YXRlcyA8LSBjKCJtYWluZSIsICJuZXcgaGFtcHNoaXJlIiwgIm1hc3NhY2h1c2V0dHMiLCAiY29ubmVjdGljdXQiLCAicmhvZGUgaXNsYW5kIiwgIm5ldyB5b3JrIiwgIm5ldyBqZXJzZXkiLCAiZGVsYXdhcmUiLCAibWFyeWxhbmQiLCAidmlyZ2luaWEiLCAibm9ydGggY2Fyb2xpbmEiLCJwZW5uc3lsdmFuaWEiKSAKCiMgVVMgU3RhdGUgTWFwIChsYW5kKQoKbGFuZF9zZiA8LSBzdF9hc19zZihtYXAoInN0YXRlIiwgcGxvdCA9IEZBTFNFLCBmaWxsID0gVFJVRSkpICU+JSAKICBmaWx0ZXIoSUQgJWluJSBTdGF0ZXMpIAoKIyBnZ3Bsb3QodXNfbWFwKSArCiAgIyBnZW9tX3NmKCkKCiMgVVMgRUVaIG1hcAoKIyBwYXRoX3dvcmxkIDwtIE15RnVuY3Rpb25zOjpteV9wYXRoKCJHIiwgZXh0cmFfcGF0aCA9ICJTcGF0aWFsL1NBVS9TQVVfU2hhcGVmaWxlIikKcGF0aF93b3JsZCA8LSAifi9Eb3dubG9hZHMvU0FVX1NoYXBlZmlsZSIKCiMgVGhlIEZpbGUKZm5hbV93b3JsZCA8LSAiU0FVRUVaX0p1bHkyMDE1LnNocCIKCiMgTG9hZCBpdCEKZWV6X3NmIDwtIHN0X3JlYWQoZHNuID0gcGF0aF93b3JsZCwKICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXIgPWZpbGVfcGF0aF9zYW5zX2V4dChmbmFtX3dvcmxkKSkgJT4lIAogIHJlbmFtZShlZXpfbmFtZSA9IE5hbWUpICU+JSAKICBzdF90cmFuc2Zvcm0oY3JzID0gNDMyNikgJT4lICMgNDMyNgogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JSAjMC4xIGZvciBwYXBlcgogIGZpbHRlcihlZXpfbmFtZSA9PSAiVVNBIChFYXN0IENvYXN0KSIpCgoKIyBnZ3Bsb3QoZWV6X3NmKSArCiMgZ2VvbV9zZihhZXMoKSxmaWxsID1OQSkKCiMgZ2dwbG90KCkgKwojICAgZ2VvbV9zZihkYXRhID0gV29ybGRfZWV6X3NmLCBhZXMoKSwgY29sb3IgPSAicmVkIikgKwojICAgZ2VvbV9zZihkYXRhID0gdXNfbWFwLCBhZXMoKSwgY29sb3IgPSAiYmx1ZSIpCgojIFVTIHN0YXRlIHdhdGVycwojIGh0dHBzOi8vY2F0YWxvZy5kYXRhLmdvdi9kYXRhc2V0L2ZlZGVyYWwtYW5kLXN0YXRlLXdhdGVycwoKIyB1c19zdGF0ZV93IDwtIHJnZGFsOjpyZWFkT0dSKGRzbiA9ICJ+L0Rvd25sb2Fkcy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMvRmVkZXJhbEFuZFN0YXRlV2F0ZXJzLmdkYiIpCnN0YXRlX3NmIDwtICBzdF9yZWFkKCJ+L0Rvd25sb2Fkcy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMvRmVkZXJhbEFuZFN0YXRlV2F0ZXJzLmdkYiIpICU+JQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIAogIG11dGF0ZShqdXJpc2RpY3RpID0gc3RyX3RvX2xvd2VyKGp1cmlzZGljdGkpKSAlPiUgCiAgZmlsdGVyKGp1cmlzZGljdGkgJWluJSBTdGF0ZXMpICU+JSAKICByZW5hbWUoc3RhdGUgPSBqdXJpc2RpY3RpKSAlPiUgCiAgIyBzdF90cmFuc2Zvcm0oY3JzID0gNDMyNikgICMgZm9yIG1hdGNoaW5nIHByb2plY3Rpb25zCiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAxMDAwMCkgIzAuMSBmb3IgcGFwZXIKCgpncmlkX3NmIDwtICBzdF9yZWFkKCIvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9EYXRhL1NwYXRpYWwvZ3JpZF9zZi9ncmlkX2Vlel9zZi5zaHAiKQoKdW5pcXVlKGxhbmRfc2YkSUQpCgpgYGAKCgojIyMgQ3JlYXRlIGJhc2Ugc2hhcGVmaWxlIGZvciBjb21wdXRhdGlvbgoKQXMgYSBmaXJzdCBzdGVwIHdlIG5lZWQgdG8gZGl2aWRlIHRoZSBORSBVUyBFRVogYW1vbmcgdGhlIGRpZmZlcmVudCBzdGF0ZXMuIEZvciB0aGF0IHdlIGV4cGFuZGVkIHN0YXRlIHdhdGVycyB1cCB0byB0aGUgMjAwIG5hdXRpY2FsIG1pbGVzIHRvIHRoZW4gZXN0aW1hdGUgdGhlIHBlcmNlbnRhZ2UgdGhhdCBlYWNoIGV4cGFuZGVkLXN0YXRlLXdhdGVycyBvY2N1cGllZC4gTm90ZSB0aGF0IGluIGFsbCBjYXNlcyB0aGVzZSBhcmVhcyBvdmVybGFwcGVkIGFuZCBwZXJjZW50YWdlcyBhY2NvdW50ZWQgZm9yIGl0LiBXZSBkaWQgdGhpcyBieSBmb2xsb3dpbmcgdGhlc2Ugc3RlcHM6CgotIDEuIEV4cGFuZCBzdGF0ZSB3YXRlcnMgdXNpbmcgYSBidWZmZXIKCi0gMi4gR3JpZCB0aGF0IGJ1ZmZlciBvbiBhIDAuMyByZXNvbHV0aW9uCgotIDMuIENyb3AgdGhlIGJ1ZmZlciB0byB0aGUgRUVaCgojIyMjIDEuIEV4cGFuZCBTcGF0aWFsIHJlZ2lvbnMgKGEuay5hICBidWZmZXJzKQoKV2Ugc2V0IGEgYnVmZmVyIG9mICo0MTAwMDAqIG0gKDQxMCBrbSwgfiAyMjEgbm0pIHRoYXQgb3ZlcnNob290cyB0aGUgRUVaIGEgYml0LCBidXQgaXMgZXZlbnR1YWxseSBjcm9wcGVkCgpgYGB7ciBidWZmZXIsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgQnVmZmVyIHN0YXRlIHdhdGVycwpzdGF0ZV9iZiA9IHN0X2J1ZmZlcihzdGF0ZV9zZiwgNDEwMDAwKSAlPiUgCiAgc3RfdHJhbnNmb3JtKDQzMjYpICU+JSAjIHRvIG1hdGNoIHNoYXBlCiAgc3Rfc2V0X2Nycyg0MzI2KQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwojIFRlc3RpbmcgYW5kIHZpc3VhbGl6aW5nIHRoZSBidWZmZXIgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCnN0YXRlX2JmX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksIGZpbGwgPSBOQSkgKwogIGdlb21fc2YoZGF0YSA9IHN0YXRlX2JmLCBhZXMoY29sb3IgPSBzdGF0ZSksIGZpbGwgPSBOQSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpCiMgICAKCiMgZ2dzYXZlKCIuLi9SZXN1bHRzL1BhcnRpYWwvc3RhdGVfd2F0ZXJzX2J1ZmZlci5wbmciLHN0YXRlX2JmX3Bsb3QpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCgpzdGF0ZV9iZl9wbG90CgpgYGAKCiMjIyMgMi4gRXhwYW5kIGdyaWQgd2l0aGluIGJ1ZmZlcgoKSGVyZSB3ZSBleHBhbmQgYSBncmlkIHdpdGhpbiB0aGUgYnVmZmVyIHNvIHdlIGNhbiBlc3RpbWF0ZSB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIHN0YXRlLgoKKk5vdGU6KiBEYXJrIGdyZXkgc2hhZGVkIGFyZWEgaXMgdGhlIGdyaWQKCmBgYHtyIGdyaWRfaW5kZXhpbmcsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQoKIyBDcmVhdGUgZ3JpZCBvZiB0aGUgcmVnaW9uCmJib3ggPC0gYyhzdF9iYm94KHN0YXRlX2JmKSkKCiMgRXhwYW5kIHRoZSBncmlkCm5lX2dyaWQgPC0gZXhwYW5kLmdyaWQoCiAgICBsb24gPSBzZXEoZnJvbSA9IGJib3hbInhtaW4iXSwgdG8gPSBiYm94WyJ4bWF4Il0sIGJ5ID0gMC4zKSwKICAgIGxhdCA9IHNlcShmcm9tID0gYmJveFsieW1pbiJdLCB0byA9IGJib3hbInltYXgiXSwgYnkgPSAwLjMpCikgJT4lIAogIHJvd2lkX3RvX2NvbHVtbigiaW5kZXgiKQoKIyAtLS0tLS0tLS0tLSAjCiMgW1RFU1RdIFBsb3QgYWxsIGxheWVycwojIC0tLS0tLS0tLS0tICMKCiMgTG9va3MgZ29vZApzdGF0ZV9zZiAlPiUKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpICU+JQogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSkrCiAgIyBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPU5BKSArCiAgIyBnZ3Bsb3QoKSsKICBnZW9tX3RpbGUoZGF0YSA9IG5lX2dyaWQsCiAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgKSwKICAgICAgICAgICAgYWxwaGEgPSAwLjIKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KQoKCmBgYAoKIyMjIyMgMi4xIE1lcmdlIGdyaWQgYW5kIGJ1ZmZlcnMKCk9uY2Ugd2UgaGF2ZSBhIGdyaWRkZWQgYXJlYSwgd2UgY29udmVydGVkIHRoZSBncmlkIHRvIGEgYHNmYCBzbyB3ZSBjYW4gbWVyZ2UgaXQgd2l0aCB0aGUgYnVmZmVyZWQgc3RhdGVzIGFuZCBmaW5hbGx5IGZpbHRlciBvdXQgZXZlcnl0aGluZyBvdXRzaWRlIHRoZSBzdGF0ZXMgcG9seWdvbgoKYGBge3IgZ3JpZF9idWZfbWVyZ2UsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGggPSAxMH0KCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgQ29udmVydCBncmlkIHRvIHNmCiMgLS0tLS0tLS0tLS0tLS0tLSAjCmdyaWRfc2YgPC0gc3RfYXNfc2YobmVfZ3JpZCwKICAgICAgICAgICAgIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwKICAgICAgICAgICAgIGNycyA9IDQzMjYpICU+JSAKICBzdF9qb2luKHN0YXRlX2JmKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzdGF0ZSkpCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgY29tcHV0YXRpb25zCiMgTm90ZSwgd2lsbCBiZSB1c2VkIGluIG5leHQgY2h1bmsKZ3JpZF9iZl9kdCA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfc2YpICU+JQogICAgc2VsZWN0KGluZGV4LHN0YXRlKQogICAgIyBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgIyBzdW1tYXJpc2UobGVuZ3RoKGluZGV4KSkKCgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIFtURVNUXSAKIyBWaXN1YWxpemF0aW9uIG9mIGdyaWQKIyAtLS0tLS0tLS0tLS0tLS0tICMKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfc2YpICsKICAgIGdlb21fc2YoYWVzKGNvbG9yID0gc3RhdGUpLCBhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSxmaWxsID1OQSkgKyAKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKSwKICAjIFNob3dpbmcgZWFjaCBzdGF0ZSBzZXBhcmF0bGV5CiAgZ2dwbG90KCkgKwogICAgZ2VvbV9zZihkYXRhID0gZ3JpZF9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLHNpemUgPSAwLjEsIGFscGhhID0gMC41KSArCiAgICBmYWNldF93cmFwKH5zdGF0ZSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpLAogIG5yb3cgPSAxKQoKYGBgCgojIyMjIDMuIENyb3AgYnVmZmVycyB0byBFRVoKCkZpbmFsbHksIHdlIGNyb3AgdGhlIGdyaWRlZCBidWZmZXJzIHRvIHdpdGhpbiB0aGUgRUVaIHRvIGNhcHR1cmUgdGhlIGFjdHVhbCB3YXRlciBzcGFjZS4KCipOb3RlOiogVGhpcyBzdGVwIHRha2VzIHF1aXRlIGEgd2hpbGUgYmVjYXVzZSBvZiB0aGUgc2l6ZSBvZiB0aGUgRUVaIHNoYXBlZmlsZS4gTm8sIHlvdSBjYW5ub3QgdXNlIGBzdF9zaW1wbGlmeSgpYCBoZXJlCgpgYGB7ciBidWZmX3RvX2VleiwgZXZhbCA9VCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCiMgSSBkb24ndCBrbm93IGhvdyB0byB1bmRvIHN0X3NpbXBsaWZ5IHNvIG5lZWQgdG8gcmUtbG9hZCB0aGUgc2hhcGVmaWxlCmVlel9zZiA8LSBzdF9yZWFkKGRzbiA9IHBhdGhfd29ybGQsCiAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyID1maWxlX3BhdGhfc2Fuc19leHQoZm5hbV93b3JsZCkpICU+JSAKICByZW5hbWUoZWV6X25hbWUgPSBOYW1lKSAlPiUgCiAgc3RfdHJhbnNmb3JtKGNycyA9IDQzMjYpICU+JSAjIDQzMjYKICBmaWx0ZXIoZWV6X25hbWUgPT0gIlVTQSAoRWFzdCBDb2FzdCkiKQoKIyBHZXQgdGhlIG92ZXJsYXBwaW5nIHNlZ21lbnRzCmdyaWRfZWV6X3NmIDwtIHN0X2ludGVyc2VjdGlvbihncmlkX3NmLGVlel9zZikKCiMgd3JpdGVfc2YoZ3JpZF9lZXpfc2YsIHBhc3RlMChteV9wYXRoKCJEIiwgIlNwYXRpYWwiKSwiZ3JpZF9lZXpfc2Yuc2hwIikpCgojIEdldCBmaW5hbCBkZiB3aXRoIGluZGV4CmdyaWRfZWV6X2RmIDwtIGFzLmRhdGEuZnJhbWUoZ3JpZF9lZXpfc2YpICU+JQogIHNlbGVjdChzdGF0ZSxpbmRleCkgJT4lIAogIGxlZnRfam9pbihuZV9ncmlkLCAKICAgICAgICAgICAgYnkgPSAiaW5kZXgiKQoKIyB3cml0ZV9jc3YoZ3JpZF9lZXpfZGYsIHBhc3RlMChteV9wYXRoKCJSIiwgIlBhcnRpYWwiKSwiZ3JpZF9lZXpfZGYuY3N2IikpCgojIFBsb3QgdG8gbWFrZSBzdXJlIG1ha2VzIHNlbnNlIChQaWNhc3NvIHN5bGUpCmdyaWRfZWV6X3NmICU+JQogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JSAjMC4xIGZvciBwYXBlcgogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KQoKYGBgCgojIyMgSW50ZXJwb2xhdGlvbiBydXRpbmUKCkluIHRoaXMgc3RlcCB3ZSBbaW50ZXJwb2xhdGVdKGh0dHBzOi8vc3dpbGtlLWdlb3NjaWVuY2UubmV0L3Bvc3Qvc3BhdGlhbF9pbnRlcnBvbGF0aW9uLykgdGhlIHN1cnZleSBkYXRhIHdpdGhpbiB0aGUgcHJldmlvdXNseSBjcmVhdGVkIGdyaWQgZm9sbG93aW5nIGEgVHJpYW5ndWxhciBJcnJlZ3VsYXIgU3VyZmFjZSBtZXRob2QuCgotIFdlIHJlbW92ZWQgY2FzZXMgd2hlcmUgYHd0Y3B1ZSA8IDBgCgojIyMjIEZ1bmN0aW9ucyBuZWVkZWQKCldlIG5lZWQgdG8gY3JlYXRlIGEgY291cGxlIG9mIGZ1bmN0aW9ucyB0byBydW4gdGhlIHdob2xlIHByb2Nlc3MKCiMjIyMjIEludGVycG9sYXRpb24gbWFpbiBmeCAodGlzKS4KClRoaXMgaXMgdGhlIG1haW4gZnVuY3Rpb24gdXNlZCB0byBpbnRlcnBvbGF0ZSB0aGUgZGF0YSBwZXIgeWVhci4gSXQgZm9sbG93cyBhIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UgbWV0aG9kIHVzaW5nIHRoZSBgaW50ZXJwOjppbnRlcnAoKWAgZnVuY3Rpb24uIElmIHlvdSB3YW50IHRvIHNlZSB0aGUgZnVuY3Rpb24gY2xpYyBvbiBgY29kZWAKCmBgYHtyIGludGVycG9sX2Z1bmN0aW9uLCBldmFsID0gVCwgZWNobyA9IFR9Cgp0aXMgPC0gZnVuY3Rpb24oaW5wdXRfZGF0YSwgZ3JpZCwgeXIsIHRheGEsIHJlZyl7CiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0gIwogICMgVGVzdGluZwogICMgcHJpbnQocGFzdGUoeXIpKQogICMgeXIgPSAxOTc2CiAgIyAtLS0tLS0tLS0tLS0tLS0gIwogIAogICMgRmlsdGVyIGRhdGEKICBkYXRhIDwtIGlucHV0X2RhdGEgJT4lIAogICAgZmlsdGVyKHllYXIgPT0geXIsCiAgICAgICAgICAgc3BwID09IHRheGEsCiAgICAgICAgICAgcmVnaW9uID09IHJlZwogICAgKSAlPiUgCiAgICAjIEF2ZXJhZ2UgZHVwbGljYXRlZCBoYXVscyBpbiB0aGUgc2FtZSBzcG90CiAgICBncm91cF9ieShyZWdpb24seWVhcixzcHAsbGF0LGxvbikgJT4lCiAgICBzdW1tYXJpc2VfYXQodmFycyh3dGNwdWUpLAogICAgICAgICAgICAgICAgIG1lYW4sbmEucm0gPSBUKSAlPiUKICAgIGZpbHRlcih3dGNwdWUgPiAwKQogICAgCiAgIyBPbmx5IGludGVycG9sYXRlIGNhc2VzIHdoZXJlIHRoZXJlIGlzIG1vcmUgdGhhbiAzIHJvd3MKICAjIE1hcmtlZCBieSB0aGUgZnVuY3Rpb24gCiAgICBpZihucm93KGRhdGEpIDw9IDMpewogICAgICBmaXRfdGluIDwtIHRpYmJsZSgpCiAgICB9ZWxzZXsKICAgICAgCiAgICAgICMgVHJpYW5ndWxhciBJcnJlZ3VsYXIgU3VyZmFjZQogICAgICBmaXRfdGluIDwtIGludGVycDo6aW50ZXJwKCAjIHVzaW5nIHtpbnRlcnB9CiAgICAgICAgeCA9IGRhdGEkbG9uLCAgICAgICAgICAgIyB0aGUgZnVuY3Rpb24gYWN0dWFsbHkgYWNjZXB0cyBjb29yZGluYXRlIHZlY3RvcnMKICAgICAgICB5ID0gZGF0YSRsYXQsCiAgICAgICAgeiA9IGRhdGEkd3RjcHVlLAogICAgICAgIHhvID0gZ3JpZCRsb24sICAgICAjIGhlcmUgd2UgYWxyZWFkeSBkZWZpbmUgdGhlIHRhcmdldCBncmlkCiAgICAgICAgeW8gPSBncmlkJGxhdCwKICAgICAgICBvdXRwdXQgPSAicG9pbnRzIgogICAgICApICU+JSAKICAgICAgICBiaW5kX2NvbHMoKSAlPiUgCiAgICAgICAgYmluZF9jb2xzKGdyaWQpICU+JQogICAgICAgIG11dGF0ZSh5ZWFyID0geXIsCiAgICAgICAgICAgICAgIHJlZ2lvbiA9IHJlZywKICAgICAgICAgICAgICAgc3BwID0gdGF4YSkgJT4lIAogICAgICAgIHNlbGVjdChpbmRleCwgc3RhdGUsIHllYXIsIHJlZ2lvbiwgc3BwLCBsb249eCwgbGF0PXksIHZhbHVlID0geikKICAgICAgCiAgICB9CiAgIAogICAgcmV0dXJuKGZpdF90aW4pCn0KCiMgVGVzdCBtZQojIE5lZWRzIHZhcmlhYmxlcyBpbiBDb250cm9sIHBhbmVsCiMgVGVzdCBubyBkYXRhOiAiQWxvc2EgYWVzdGl2YWxpcyIsIHJlZyA9ICJOb3J0aGVhc3QgVVMgRmFsbCIsIHlyID0gMTk3NCAKIyB0aXMoaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9kZiwgdGF4YSA9ICJJbGxleCBpbGxlY2Vicm9zdXMiLCByZWcgPSAiTm9ydGhlYXN0IFVTIEZhbGwiLCB5ciA9IDE5NzMpCgoKCiMgbGFwcGx5KHllYXJzLHRpcyxpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWRfZWV6X2RmLCB0YXhhID0gIklsbGV4IGlsbGVjZWJyb3N1cyIsIHJlZyA9IHJlZ2lvbnNbMl0pCgpgYGAKCiMjIyMjIFJ1biBmdW5jdGlvbgoKVGhpcyBpcyBhIHN1Yi1mdW5jdGlvbiB0aGF0IHJ1bnMgdGhlIGB0aXMoKWAgZnVuY3Rpb24gYnkgdGF4YSBhbmQgcmVnaW9uLiBJdCBzYXZlcyB0aGUgb3V0cHV0IGFzIGEgLmNzdiBmaWxlIGZvciBlYWNoIHNwZWNpZXMuIAoKYGBge3IgaW50ZXJwb2xfcnVuX2Z1biwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKCnJ1bl90aXMgPC0gZnVuY3Rpb24oaW5wdXRfZGF0YSwgZ3JpZCwgeWVhcnMsIHRheGEsIHJlZyl7CiAgCiAgCiAgIyBSdW4gdGlzIGZvciBzcGVjaWVzIGFuZCBzdXJ2ZXlzCiAgZm9yKHIgaW4gMToyKXsKICAgIAogICAgcGFydGlhbF9kZiA8LSBiaW5kX3Jvd3MoCiAgICAgIGxhcHBseSh5ZWFycyx0aXMsaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9kZiwgdGF4YSA9IHRheGEsIHJlZyA9IHJlZ2lvbnNbcl0pCiAgICApCiAgICAKICAgIGlmKHIgPT0gMSl7CiAgICAgIGhpc3RvcmljX3RpZiA8LSBwYXJ0aWFsX2RmCiAgICB9ZWxzZXsKICAgICAgaGlzdG9yaWNfdGlmIDwtIGJpbmRfcm93cyhoaXN0b3JpY190aWYscGFydGlhbF9kZikKICAgIH0KICAgIAogIH0KICAKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKICAjIFNhdmUgZGF0YXNldCBwZXIgc3BlY2llcwogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwogIAogICMgU2V0IGZpbGUgbmFtZQogIG5hbWUgPC0gcGFzdGUwKCJ0aWZfIixzdHJfcmVwbGFjZSh0YXhhLCIgIiwiXyIpLCIuY3N2IikKICAKICAjIFNldCBwYXRoIG5hbWUKICBzYXZlX3BhdGggPC0gbXlfcGF0aCgiUiIsIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIpCiAgCiAgIyBTZXQgY29tcGxldGUgcGF0aAogIHNhdmVfbmFtZSA8LSBwYXN0ZTAoc2F2ZV9wYXRoLG5hbWUpCiAgCiAgIyBDcmVhdGUgZm9sZGVyIGlmIGl0IGRvZXMgbm90IGV4aXN0CiAgaWYoZmlsZS5leGlzdHMoc2F2ZV9wYXRoKSA9PSBGKXsKICAgIGRpci5jcmVhdGUoc2F2ZV9wYXRoKQogIH0KICAKICAjICBTYXZlIGZpbGUKICB3cml0ZV9jc3YoaGlzdG9yaWNfdGlmLHNhdmVfbmFtZSkKICAKICByZXR1cm5fbXNnIDwtIHBhc3RlKCJJbnRlcnBvbGF0aW9uIGRvbmUgZm9yIiwgdGF4YSkKICAKICByZXR1cm4ocmV0dXJuX21zZykKICAKICAKfQoKIyBUZXN0IG1lCiAgICAjIHJ1bl90aXMoaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9kZiwgdGF4YSA9ICJDZW50cm9wcmlzdGlzIHN0cmlhdGEiLCB5ZWFycyA9IHllYXJzLCByZWcgPSByZWdpb25zKQoKYGBgCgoKIyMjIyBTdXJ2ZXkgZGF0YQoKVGhlIGludGVycG9sYXRpb24gd2FzIGRvbmUgd2l0aCBOT0FBIE5vcnRoZWFzdCBGaXNoZXJpZXMgU2NpZW5jZSBDZW50ZXIgU3ByaW5nIGFuZCBGYWxsIEJvdHRvbSBUcmF3bCBTdXJ2ZXlzIFtkYXRhXShodHRwczovL3d3dy5maXNoZXJpZXMubm9hYS5nb3YvcmVnaW9uL25ldy1lbmdsYW5kLW1pZC1hdGxhbnRpYyNzY2llbmNlKSBwcm92aWRlZCBieSBbT2NlYW4gYWRhcHRdKGh0dHBzOi8vb2NlYW5hZGFwdC5ydXRnZXJzLmVkdS8pLiBEYXRhIHdhcyBhY2Nlc3NlZCB0cm91Z2ggdGhlIFtHaXRodWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9waW5za3lsYWIvT2NlYW5BZGFwdCkuCgoqSW4gcHJpbWFyeSBwdWJsaWNhdGlvbnMgdXNpbmcgZGF0YSBmcm9tIHRoZSBkYXRhYmFzZSwgcGxlYXNlIGNpdGUgUGluc2t5IGV0IGFsLiAyMDEzLiBNYXJpbmUgdGF4YSB0cmFjayBsb2NhbCBjbGltYXRlIHZlbG9jaXRpZXMuIFNjaWVuY2UgMzQxOiAxMjM5LTEyNDIgZG9pOiAxMC4xMTI2L3NjaWVuY2UuMTIzOTM1MiwgYXMgd2VsbCBhcyB0aGUgb3JpZ2luYWwgZGF0YSBzb3VyY2VzLioKCi0gVXNpbmcgb25seSB0aGUgTm9ydGhlYXN0IFVTIEZhbGwgYW5kIFNwcmluZyBib3R0b20gdHJhd2wgc3VydmV5IGRhdGEgZm9yIG5vdwoKIyMjIyMgU3BsaXR0aW5nIHVwIGRhdGEKCi0gTm8gcGFydCBvbiBzcGF0aWFsIGFuYWx5c2lzLiBDYW4gYmUgaWdub3JlZC4gCgpUaGlzIGlzIGp1c3QgYSBzdWItc3RlcCB0byBzcGxpdCB1cCB0aGUgZGF0YSBpbnRvIHNpbmdsZSBzcGVjaWVzIGZpbGVzLiBUaGlzIG1ha2VzIHRoZSBhcHAgZmFzdGVyIGFzIGl0IG9ubHkgbmVlZHMgdG8gbG9hZCBzcGVjaWVzIHNwZWNpZmljIGRhdGEsIHJhdGhlciB0aGFuIGFsbCB0aGUgZGF0YSBhdCBkZSBiZWdpbmluZy4gCgpgYGB7ciBkYXRfZXhwbG9kZWQsIGV2YWwgPSBULCBlY2hvID0gRiwgZmlnLndpZHRoID0gOX0KCm9jZWFuX2RhdGEgPC0gcmVhZFJEUygiL1ZvbHVtZXMvRW50ZXJwcmlzZS9EYXRhL3BpbnNreWxhYi1PY2VhbkFkYXB0LTk2NmFkZjAvZGF0YV9jbGVhbi9kYXRfZXhwbG9kZWQucmRzIikgIyU+JSAKICAjIGZpbHRlcihzcHAgPT0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsCiAgICAgICAjIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikpICNObyBtb3JlIHNlYXNvbnMKCgpzcHBfZGF0YSA8LSBmdW5jdGlvbihzcHApewogIAogIG5hbWVfc2F2ZSA8LSBwYXN0ZTAobXlfcGF0aCgiRCIsIlNwcC9PYnNlcnZhdGlvbiIpLCJvYnNfIixzdHJfcmVwbGFjZShzcHBbMV0sICIgIiwgIl8iKSwiLmNzdiIpCgpvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIoc3BwID09IHNwcCwKICAgICAgIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKICAgICAgICkgJT4lIAogIHdyaXRlX2NzdiguLCBuYW1lX3NhdmUpCiAgCn0KCnNwcF9saXN0IDwtIG9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihyZWdpb24gJWluJSByZWdpb25zLAogICAgICAgICBzcHAgIT0gIk5BIikgJT4lIAogIHB1bGwoc3BwKSAlPiUgCiAgdW5pcXVlKCkKICAKCmxhcHBseShzcHBfbGlzdCwgc3BwX2RhdGEpCgoKc3Vic2V0X2RhdGEgPC0gb2NlYW5fZGF0YSAlPiUgCiAgZmlsdGVyKHNwcCA9PSAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiwKICAgICAgIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKICAgICAgICkKCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBzdWJzZXQoc3Vic2V0X2RhdGEsIHd0Y3B1ZSA9IDAuMCksCiAgICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgIHggPSBsb24sCiAgICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgICksCiAgICAgICAgICAgICBjb2xvciA9ICJncmV5OTUiCiAgKSArCiAgZ2VvbV9wb2ludChkYXRhID0gc3Vic2V0KHN1YnNldF9kYXRhLCB3dGNwdWUgPiAwKSwKICAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICAgeCA9IGxvbiwKICAgICAgICAgICAgICAgeSA9IGxhdCwKICAgICAgICAgICAgICAgY29sb3IgPSBsb2cxMCh3dGNwdWUpCiAgICAgICAgICAgICApLAogICAgICAgICAgICAgc2l6ZSA9IDEKICApICsKICBzY2FsZV9jb2xvcl9kaXN0aWxsZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICBndWlkZV9sZWdlbmQodGl0bGUgPSAiV0NQVUUgcGVyIEhhdWwgKGxvZzEwKSIpKSArIAogIGNvb3JkX3NmKHhsaW0gPSBjKC03NiwgLTY1KSx5bGltID0gYygzNSwgNDUpKSArCiAgTXlGdW5jdGlvbnM6Om15X2dndGhlbWVfbSgpICsKICBmYWNldF93cmFwKH5yZWdpb24pCgpgYGAKCiMjIyMgQ29udHJvbCBQYW5uZWwKClRoaXMgaXMgd2hlcmUgd2UgbG9hZCB0aGUgcmVxdWlyZWQgZGF0YSBhbmQgcHJlcGFyZSB0byBydW4gdGhlIGludGVycG9sYXRpb24gZnVuY3Rpb24uIE5vdGUgdGhhdCBzb21lIG9mIHRoZSBkYXRhIGhlcmUgaGFzIGJlZW4gcHJldmlvdXNseSBjcmVhdGVkIAoKYGBge3IgY29udHJvX3Bhbm5lbCwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBMb2FkIGdyaWQgZGYKZ3JpZF9lZXpfZGYgPC0gbXlfcGF0aCgiRCIsIlNwYXRpYWwiLCJncmlkX2Vlel9kZi5jc3YiLCByZWFkID0gVCkKCiMgUnVuIGludGVycG9sYXRpb24gZm9yIGFsbCB5ZWFycwp5ZWFycyA8LSBzZXEoMTk3MywyMDE5LDEpCgojIHJlZ2lvbnMKcmVnaW9ucyA8LSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpCgojIHNwZWNpZXMgbGlzdApzcHAgPC0gb2NlYW5fZGF0YSAlPiUgCiAgZmlsdGVyKHJlZ2lvbiAlaW4lIHJlZ2lvbnMsCiAgICAgICAgIHNwcCAhPSAiTkEiKSAlPiUgCiAgcHVsbChzcHApICU+JSAKICB1bmlxdWUoKQoKCiMgRG91YmxlIGNoZWNrIHJ1bnMKCnNwcF9ydW5zIDwtIHRpYmJsZSh0YXhhID0gKGxpc3QuZmlsZXMobXlfcGF0aCgiUiIsIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIpKSkpICU+JQogIG11dGF0ZSgKICAgIHRheGEgPSBzdHJfcmVtb3ZlKHRheGEsICJ0aWZfIiksCiAgICB0YXhhID0gc3RyX3JlbW92ZSh0YXhhLCAiLmNzdiIpLAogICAgdGF4YSA9IHN0cl9yZXBsYWNlKHRheGEsICJfIiwgIiAiKQogICkgCgojIE1pc3NpbmcgcnVucwpzcHAgPC0gdGliYmxlKHRheGE9c3BwKSAlPiUgCiAgYW50aV9qb2luKHNwcF9ydW5zKSAlPiUgCiAgcHVsbCh0YXhhKQoKCmBgYAoKIyMjIyBSdW4gcm91dGluZQoKSGVyZSB3ZSBqdXN0IHJ1biB0aGUgcm91dGluZSBmb3IgZWFjaCBvZiB0aGUgc3BlY2llcyBwcmVzZW50IGluIHRoZSBOb3J0aGVhc3QgVVMgRmFsbCBhbmQgU3ByaW5nIHN1cnZleXMgYmV0d2VlbiAxOTczIGFuZCAyMDE5LiAKCi0gTm90ZSB0aGVyZSBhcmUgNDMgaWRlbnRpZmllZCB0YXhhCi0gU29tZSB0YXhhIGRvIG5vdCBoYXZlIHByZXNlbmNlIGRhdGEgaW4gc29tZSB5ZWFycwoKYGBge3IgcnVuX3JvdXRpbmUsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgc2luZ2xlIHNwZWNpZXMgcnVuCiMgcnVuX3RpcyhpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwKIyAgICAgICAgIGdyaWQgPSBncmlkX2Vlel9kZiwKIyAgICAgICAgIHllYXJzID0geWVhcnMsCiMgICAgICAgICByZWcgPSByZWdpb25zLAojICAgICAgICAgdGF4YSA9ICJJbGxleCBpbGxlY2Vicm9zdXMiCiMgKQoKCiMgUnVuIHRoZW0gYWxsIGluIHBhcmFsbGVsCnBhcmFsbGVsOjptY2xhcHBseShzcHAsCiAgICAgICAgICAgICAgICAgICBydW5fdGlzLCAKICAgICAgICAgICAgICAgICAgIGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLAogICAgICAgICAgICAgICAgICAgZ3JpZCA9IGdyaWRfZWV6X2RmLAogICAgICAgICAgICAgICAgICAgeWVhcnMgPSB5ZWFycywKICAgICAgICAgICAgICAgICAgIHJlZyA9IHJlZ2lvbnMKKQoKCmBgYAoKIyBSZXN1bHRzCgpUaGlzIHNlY3Rpb24gc2hvd3MgcHJlbGltaW5hcnkgcmVzdWx0cyBmb3IgQmxhY2sgc2VhIGJhc3MgKCpDZW50cm9wcmlzdGlzIHN0cmlhdGEqKS4KCmBgYHtyIGxvYWRfZGF0YSwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBMb2FkIGludGVycG9sYXRlZCBkYXRhCiMgIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIKIyAKaGlzdG9yaWNfdGlmIDwtIG15X3BhdGgoIlIiLCJQYXJ0aWFsL0ludGVycG9sYXRpb24iLCJ0aWZfQ2VudHJvcHJpc3Rpc19zdHJpYXRhLmNzdiIsIHJlYWQgPSBUKQoKIyBTcGF0aWFsIGRhdGEKClN0YXRlcyA8LSBjKCJtYWluZSIsICJuZXcgaGFtcHNoaXJlIiwgIm1hc3NhY2h1c2V0dHMiLCAiY29ubmVjdGljdXQiLCAicmhvZGUgaXNsYW5kIiwgIm5ldyB5b3JrIiwgIm5ldyBqZXJzZXkiLCAiZGVsYXdhcmUiLCAibWFyeWxhbmQiLCAidmlyZ2luaWEiLCAibm9ydGggY2Fyb2xpbmEiLCJwZW5uc3lsdmFuaWEiKSAKCiMgVVMgU3RhdGUgTWFwIChsYW5kKQoKbGFuZF9zZiA8LSBzdF9hc19zZihtYXAoInN0YXRlIiwgcGxvdCA9IEZBTFNFLCBmaWxsID0gVFJVRSkpICU+JSAKICBmaWx0ZXIoSUQgJWluJSBTdGF0ZXMpIAoKCiMgUGVyaW9kcwpwZXJpb2RzIDwtdGliYmxlKAogIHBlcmlvZCA9IGMocmVwKCJhIGVhcmx5IiwxMiksCiAgICAgICAgICAgICByZXAoImIgbWlkIiwxMiksCiAgICAgICAgICAgICByZXAoImMgbGF0ZSIsMTIpLAogICAgICAgICAgICAgcmVwKCJkIG5vdyIsMTIpCiAgICAgICAgICAgICApLAogIHllYXIgPSBjKHNlcSgxOTcyLDE5ODQsMSksCiAgICAgICAgICAgIHNlcSgxOTg1LDE5OTcsMSksCiAgICAgICAgICAgIHNlcSgxOTk4LDIwMTEsMSksCiAgICAgICAgICAgIHNlcSgyMDEyLDIwMTksMSkKICAgICAgICAgICAgKQogICkKCiMgU3RhdGUgcGFsbGV0CgpzdGF0ZV9wYWxsZXQgPC0gYyh3ZXNfcGFsZXR0ZShuID0gNSwgbmFtZSA9ICJEYXJqZWVsaW5nMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VzX3BhbGV0dGUobiA9IDUsIG5hbWUgPSAiRGFyamVlbGluZzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlc19wYWxldHRlKG4gPSAzLCBuYW1lID0gIlJveWFsMSIpCiAgICAgICAgICAgICAgICAgICkKCgoKIyBwcmludCBmb3Igbm90ZWJvb2sKaGVhZChoaXN0b3JpY190aWYpCmBgYAoKCiMjIEF2ZXJhZ2UgcHJvcG9ydGlvbgoKVGhpcyBtYXAgc2hvd3MgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiB0aGUgZXh0cmFwb2xhdGVkIHZhbHVlIGZyb20gdGhlIHdob2xlIHN0dWR5IHBlcmlvZCB3aXRoaW4gZWFjaCBTdGF0ZSdzIHdhdGVyLgoKKk5vdGU6KiBHcmV5IHRpbGVzIHJlcHJlc2VudCBgTkFzYAoKYGBge3IgYXJlYV9tYXBfc3RhdGUsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEyfQoKIGRhdGFfZ3JpZCA8LSBoaXN0b3JpY190aWYgJT4lIAogICMgbGVmdF9qb2luKHBlcmlvZHMpICU+JSAKICAjIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scGVyaW9kKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUsbGF0LGxvbixyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgcmVuYW1lKElEID0gc3RhdGUpCgpnZ3Bsb3QoZGF0YV9ncmlkKSArCiAgZ2VvbV90aWxlKAogICAgYWVzKAogICAgICB4ID0gbG9uLAogICAgICB5ID0gbGF0LAogICAgICBmaWxsID0gbWVhbiwKICAgICAgY29sID0gbWVhbgogICAgKQogICkgKwogIGZhY2V0X3dyYXAofiBJRCAgKyAgcmVnaW9uLAogICAgICAgICAgICAgbmNvbCA9IDQpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoIk1lYW4gUHJvcG9ydGlvbiIsIGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfdmlyaWRpcygiTWVhbiBQcm9wb3J0aW9uIiwgYWxwaGEgPSAwLjgpCmBgYAoKIyMgUHJvcG9ydGlvbiBDaGFuZ2UKCkhlcmUgd2Ugc2hvdyB0aGUgYXZlcmFnZSBwcm9wb3J0aW9uIG9mIHRoZSBpbnRlcnBvbGF0aW9uIGJ5IFN0YXRlIGFuZCB0aW1lIHBlcmlvZC4gVGltZSBwZXJpb2RzIHdlcmUgYXJiaXRyYXJ5IGRlZmluZWQgYXM7CgotIEVhcmx5OyAxOTcyIHRvIDE5ODQKLSBNaWQ7IDE5ODUgdG8gMTk5NwotIExhdGU7IDE5OTggdG8gMjAxMQotIE5vdzsgMjAxMiB0byAyMDE5CgoqTm90ZXM6KiBUbyBwYW5lbCByZXByZXNlbnRzIEZhbGwgc3VydmV5IGFuZCBib3R0b20gcGFuZWwgU3ByaW5nLiBUaGlzIGNvbXB1dGF0aW9uIGNvbnNpZGVycyB0aGUgT3ZlcmxhcHBpbmcgb2Ygc3RhdGUgd2F0ZXJzLgoKYGBge3IgYXJlYV9tYXAsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoID0gMTB9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY190aWYgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGxlZnRfam9pbihwZXJpb2RzLAogICAgICAgICAgICBieSA9ICJ5ZWFyIikgJT4lIAogIGdyb3VwX2J5KElEID0gc3RhdGUscGVyaW9kLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShtZWFuX3BlciA9IHJvdW5kKG1lYW4ocGVyY2VudGFnZSkpLC5ncm91cHMgPSAiZHJvcCIpCiAgCiMgY2hlY2sgcGVyY2VudGFnZXMKIyBzdGF0ZV9maXQgJT4lIAojICAgZ3JvdXBfYnkocGVyaW9kKSAlPiUgCiMgICBzdW1tYXJpc2Uoc3VtKG1lYW5fcGVyKSkKCgpsYW5kX3NmICU+JSAKICBsZWZ0X2pvaW4oc3RhdGVfZml0LAogICAgICAgICAgICBieSA9ICJJRCIpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IG1lYW5fcGVyKSkgKwogIHZpcmlkaXM6OnNjYWxlX2ZpbGxfdmlyaWRpcygiTWVhbiBQcm9wb3J0aW9uIiwgYWxwaGEgPSAwLjgpICsKICBmYWNldF93cmFwKH5yZWdpb24gKyBwZXJpb2QsIG5yb3cgPSAyKSArCiAgbXlfZ2d0aGVtZV9tKCkKCmBgYAoKIyMgQXJlYSBwbG90CgpUaGlzIGdyYXBoIHNob3dzIHRoZSBwcm9wb3J0aW9uIG9mIHRoZSBpbnRlcnBvbGF0aW9uIHZhbHVlIGVhY2ggU3RhdGUgaGFzIG92ZXIgdGltZS4KCipOb3RlOiogVGhpcyBwbG90IGlzIGludGVyYWN0aXZlLiBGb3IgZWFzZSBjb21wYXJpc29uIGJldHdlZW4gU3RhdGVzIHlvdSBjYW47CgotICpPbmUqIGNsaWNrIG9uIGFueSBTdGF0ZSB0byAqcmVtb3ZlKiBpdCBmcm9tIHRoZSBwbG90IAotICpUd28qIGNsaWNrcyBvbiBhbnkgU3RhdGUgdG8gKmlzb2xhdGUgaXQqIGZyb20gdGhlIHBsb3QgKG90aGVyIHN0YXRlcyBjYW4gdGhlbiBiZSBhZGRlZCBieSBqdXN0IGNsaWNraW5nIG9uIHRoZW0pLgotIFRoZSBib3R0b20gcGFuZWwgYWxsb3dzIHlvdSB0byByZWR1Y2UgdGhlIHRpbWUgZnJhbWUKCmBgYHtyIGFyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkKCnAgPC0gZ2dwbG90KHN0YXRlX2ZpdCkgKwogIGdlb21fYXJlYSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSByb3VuZChwZXJjZW50YWdlKSwKICAgICAgZmlsbCA9IHN0YXRlCiAgICApCiAgKSArCiAgeWxhYigiUGVyY2VudGFnZSAoJSkiKSArCiAgIyB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBULCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogIE15RnVuY3Rpb25zOjpteV9nZ3RoZW1lX3AoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBuY29sID0gMSkKCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUKICByYW5nZXNsaWRlcigpCgpgYGAKCiMjIEFyZWEgcGxvdCAocnVubmluZyBtZWFuKQoKVGhpcyBncmFwaCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIFN0YXRlIHNtb290aGVkIG92ZXIgYSAqMTAgeWVhcnMgcnVubmluZyBtZWFuKiouIEl0IGFsbG93cyB0byBiZXR0ZXIgc2VlIGluY3JlYXNpbmcgYW5kIGRlY3JlYXNpbmcgdHJlbmRzLgoKKk5vdGU6KiBUaGlzIHBsb3QgaXMgYWxzbyBpbnRlcmFjdGl2ZSBhbmQgdGh1cywgZm9sbG93cyB0aGUgc2FtZSBvcHRpb25zIG9mIHRoZSBwcmV2aW91cyBvbmUuCgpgYGB7ciBhcmVhX2xtX3Bsb3QsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMgZ3JvdXAgYnkgc3RhdGUKc3RhdGVfZml0IDwtIGhpc3RvcmljX3RpZiAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24sLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHJlZ2lvbikgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKQoKIyBQbG90IG1lCnAgPC0gZ2dwbG90KHN0YXRlX2ZpdCkgKwogIGdlb21fYXJlYSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSByb3VuZChSTWVhbiksCiAgICAgIGZpbGwgPSBzdGF0ZQogICAgKQogICkgKwogIHlsYWIoIjEwIHlycyBydW5uaW5nIGF2ZXJhZ2UgKCUpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpCgpzdXBwcmVzc1dhcm5pbmdzKApnZ3Bsb3RseShwLAogICAgICAgICBkeW5hbWljVGlja3MgPSBUUlVFKSAlPiUgCiAgbGF5b3V0KGhvdmVybW9kZSA9ICJ4IikgJT4lIAogICMgYWRkX3RyYWNlKCkgJT4lIAogIHJhbmdlc2xpZGVyKCkKKQoKYGBgCg==